-
Notifications
You must be signed in to change notification settings - Fork 12
Logic to handle optional_extra in Vision Excel converter input #344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements logic to handle optional extra columns in the tabular converter, addressing issue #338. The feature allows specifying columns that should be included in extra_info if present but won't cause conversion failure if missing.
Key Changes:
- Added
allow_missingparameter throughout the column definition parsing chain to support optional columns - Implemented
optional_extrawrapper in column definitions to mark columns as optional - Enhanced error handling to gracefully skip missing optional columns while preserving required column behavior
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/power_grid_model_io/converters/tabular_converter.py | Core implementation of optional_extra logic with allow_missing parameter propagation and empty DataFrame handling for missing columns |
| tests/unit/converters/test_tabular_converter.py | Comprehensive test coverage for optional_extra feature including edge cases and integration tests |
| docs/converters/vision_converter.md | Documentation explaining optional_extra syntax, behavior, and use cases for Vision Excel exports |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 10 out of 13 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
| extra: | ||
| - ID # Required - fails if missing | ||
| - Name # Required - fails if missing | ||
| - optional_extra: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens if an element is specified in both the required and optional?
extra:
- ID # Required - fails if missing
- optional_extra:
- ID # Optional - skipped if missingI believe that the default should be that required precedes optional, so maybe we need to add an explicit test case for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| allow_missing: bool = False, | ||
| ) -> pd.DataFrame: | ||
| """Interpret the column definition and extract/convert/create the data as a pandas DataFrame. | ||
| Args: | ||
| data: TabularData: | ||
| table: str: | ||
| col_def: Any: | ||
| extra_info: Optional[ExtraInfo]: | ||
| allow_missing: bool: If True, missing columns will return empty DataFrame instead of raising KeyError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether this is the right solution. If I understand correctly, this parameter is needed due to the recursion, right? Would there be a world in which either no recursion is needed, or in which we can do without this allow_missing? It feels bugprone
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| allow_missing: bool = False, | ||
| ) -> pd.DataFrame: | ||
| """Interpret the column definition and extract/convert/create the data as a pandas DataFrame. | ||
| Args: | ||
| data: TabularData: | ||
| table: str: | ||
| col_def: Any: | ||
| extra_info: Optional[ExtraInfo]: | ||
| allow_missing: bool: If True, missing columns will return empty DataFrame instead of raising KeyError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add allow_missing to the tests (either by testing that it works as intended + that all sub-calls to the mocks are made correctly, and/or by raising an error if it is set but recursion level is not 0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| col_def: Any, | ||
| table_mask: Optional[np.ndarray], | ||
| extra_info: Optional[ExtraInfo], | ||
| allow_missing: bool = False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please make a keyword arg
| allow_missing: bool = False, | |
| *, | |
| allow_missing: bool = False, |
optionally, you can even demand that the other fields are keyword args as well (that's OK because it's a protected member function so we can change the interface without any issues)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a private function and we can change it at will. Does it really matter if we have allow_missing as kwarg? It is a matter of preference? Is it best practice? Or is there other reason? I don't have a strong opinion, but I wish to understand better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the reason is that it's very bugprone unless we thoroughly test this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a test that check the behavior when an attribute is added to both extra and optional_extra, e.g.
extra:
- ID
- optional_extra:
- IDThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| col_def: Any, | ||
| table_mask: Optional[np.ndarray], | ||
| extra_info: Optional[ExtraInfo], | ||
| allow_missing: bool = False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's a private function and we can change it at will. Does it really matter if we have allow_missing as kwarg? It is a matter of preference? Is it best practice? Or is there other reason? I don't have a strong opinion, but I wish to understand better.
| return self._parse_col_def_composite( | ||
| data=data, table=table, col_def=optional_cols, table_mask=table_mask, allow_missing=True | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only place where I see allow_missing=True. Why is that? Is it because it's only relevant when the underlying structure is a dict, hence then is only when the "new" extra optional parameters matter? Why isn't it relevant bellow when we have a list instead?
I don't think I've ever worked in this repo, so genuinely asking. I'd appreciate tech review over this :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now only optional_extra are fields we attribute the 'optional' to its existence.
Comments from Martijn Co-authored-by: Martijn Govers <martijn.govers@alliander.com> Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Comments from Martijn Co-authored-by: Martijn Govers <martijn.govers@alliander.com> Signed-off-by: Jerry Guo <6221579+Jerry-Jinfeng-Guo@users.noreply.github.com>
Signed-off-by: Jerry Guo <Jerry.Jinfeng.Guo@alliander.com>
|



Closes #338
In this PR:
optional_extra